package com.example.hellomap.rest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

public class ServerInterface {
	public final static String host="10.0.2.2";
	
    public static void post(String uri, Object obj) {
    	boolean postIsOk=true;
    	try {   
    		URL url = new URL("http://"+host+":8080/api/"+uri);
    		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    		conn.setDoOutput(true);
    		conn.setRequestMethod("POST");
    		conn.setRequestProperty("Content-Type", "application/json");
    		String input="";
    		if (uri.charAt(0)=='u') {
    			users user = (users)obj;
	    		if (user.getId()!=null) {	
					input = "{\"_id\":\""+user.getId()+"\"";
		    		if (user.getEmail()!=null) {
		    			 input += ", \"email\":\""+user.getEmail()+"\"";
		    		}
		    		if (user.getPass()!=null) {
		    			 input += ", \"pass\":\""+user.getPass()+"\"";
		    		}    	
		    		input+="}";
	    		} else {
	    			postIsOk=false;
	    		}
    		} else if (uri.charAt(0)=='e') {
    			events event = (events)obj;
	    			if (event.getId()!=null) {	
					input = "{\"_id\":\""+event.getId()+"\"";
		    		if (event.getName()!=null) {
		    			 input += ", \"name\":\""+event.getName()+"\"";
		    		}
		    		if (event.getPlace()!=null) {
		    			 input += ", \"place\":\""+event.getPlace()+"\"";
		    		}  
		    		if (event.getTo()!=null) {
		    			 input += ", \"to\":\""+event.getTo()+"\"";
		    		} 
		    		if (event.getFrom()!=null) {
		    			 input += ", \"from\":\""+event.getFrom()+"\"";
		    		} 
		    		input+="}";
    			} else {
	    			postIsOk=false;
	    		}
    		} else if (uri.charAt(0)=='p') { //TODO: test places+calendars
    			places place = (places)obj;
    			if (place.getId()!=null) {	
	    			input = "{\"_id\":\""+place.getId()+"\"";
		    		if (place.getZip()!=0) {
		    			 input += ", \"zip\":\""+place.getZip()+"\"";
		    		}
		    		if (place.getLat()!=0 || place.getLon()!=0) {
		    			//input += ", \"loc\":{\"lon\":"+place.getLon()+",\"lat\":"+place.getLat()+"}";
		    			input += ", \"coordinates\":["+place.getLon()+","+place.getLat()+"]";
		    		}
		    		input+="}";
		    		System.out.println("The input is: "+input);
    			} else {
	    			postIsOk=false;
	    		}
    		} else if (uri.charAt(0)=='c') {
    			calendars calendar = (calendars)obj;
    			if (calendar.getUserId()!=null) {
    				input = "{\"uid\":\""+calendar.getUserId()+"\"";
	    			input += ", \"name\":\""+calendar.getName()+"\""; //legyen az eseménynek neve, usere
	    			if (calendar.getTo()!=null) {
		    			 input += ", \"to\":\""+calendar.getTo()+"\"";
		    		} 
		    		if (calendar.getFrom()!=null) {
		    			 input += ", \"from\":\""+calendar.getFrom()+"\"";
		    		}
		    		if (calendar.getLat()!=0 || calendar.getLon()!=0) {
		    			input += ", \"coordinates\":["+calendar.getLon()+","+calendar.getLat()+"]";
		    		} 
		    		input+="}";
    			}
    		}
    		//System.out.println(input);
    		if (postIsOk) {
	    		OutputStream os = conn.getOutputStream();
				os.write(input.getBytes());
				os.flush();
		 
				BufferedReader br = new BufferedReader(new InputStreamReader(
						(conn.getInputStream())));
		 
				String output;
				System.out.println("Output from Server .... \n");
				while ((output = br.readLine()) != null) {
					System.out.println(output);
				}
    		} else {
    			System.out.println("The id is not existing!");
    		}
			conn.disconnect();
    	  } catch (MalformedURLException e) {     
    		e.printStackTrace();     
    	  } catch (IOException e) {     
    		e.printStackTrace();     
    	  }    			
	}

	public static void delete(String collName, String id) {
    	try {    		 
    		URL url = new URL("http://"+host+":8080/api/"+collName+"/"+id);
    		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    		conn.setRequestMethod("DELETE");
    		conn.setRequestProperty("Accept", "application/json");     
    		if (conn.getResponseCode() != 200) {
    			throw new RuntimeException("Failed : HTTP error code : "
    					+ conn.getResponseCode());
    		}     
    		BufferedReader br = new BufferedReader(new InputStreamReader(
    			(conn.getInputStream())));     
    		String output;
    		while ((output = br.readLine()) != null) {
    			System.out.println(output);
    		}     
    		conn.disconnect();     
    	  } catch (MalformedURLException e) {     
    		e.printStackTrace();     
    	  } catch (IOException e) {     
    		e.printStackTrace();     
    	  }    	
	}

	//(create or) update
	public static void updateUser(String username, String data, String field) { //field should be: pass, public_events, event_id, remove_event. See more in the documentation
		if (field.equals("pass") || field.equals("public_events") || field.equals("event_id") || field.equals("remove_event")) {
	    	try {
	    		URL url = new URL("http://"+host+":8080/api/users/"+username);
				HttpURLConnection conn = putConn(url);   	     	 
				String input = "{\""+field+"\":\""+data+"\"}";
				updateData(conn.getOutputStream(), input, conn);
	    	} catch (IOException e) {     
	  	    	e.printStackTrace();     
	  	    }
		} else {
			System.out.println("It is a not valid field type");
		}
	}
	
	public static void updateEvent(String id, String data, String field) { //field should be: name, from, to, place(string)
		if (field.equals("name") || field.equals("from") || field.equals("to") || field.equals("place")) {
	    	try {
	    		URL url = new URL("http://"+host+":8080/api/events/"+id);
				HttpURLConnection conn = putConn(url);    	     	 
				String input = "{\""+field+"\":\""+data+"\"}";
				updateData(conn.getOutputStream(), input, conn);
	    	} catch (IOException e) {     
	  	    	e.printStackTrace();     
	  	    }
		} else {
			System.out.println("It is a not valid field type. ");
		}
	}
	
	public static void updateCalendar(String uid, String data, String field) { //field should be: name, from, to, place(loc)
		if (field.equals("name") || field.equals("from") || field.equals("to") || field.equals("place")) {
	    	try {
	    		URL url = new URL("http://"+host+":8080/api/calendars/"+uid);
				HttpURLConnection conn = putConn(url);    	     	 
				String input = "{\""+field+"\":\""+data+"\"}";
				updateData(conn.getOutputStream(), input, conn);
	    	} catch (IOException e) {     
	  	    	e.printStackTrace();     
	  	    }
		} else {
			System.out.println("It is a not valid field type. ");
		}
	}
	
	public static void updateData(OutputStream os, String input, HttpURLConnection conn){
		try {
			os.write(input.getBytes());
			os.flush();
			BufferedReader br = new BufferedReader(new InputStreamReader(
					(conn.getInputStream())));    	 
			String output;
			while ((output = br.readLine()) != null) {
				System.out.println(output);
			}    	 
			conn.disconnect();
		} catch (IOException e) {     
  	    	e.printStackTrace();     
  	    }   
	}
	
	public static HttpURLConnection putConn(URL url) {
		HttpURLConnection conn = null;
		try {
			conn = (HttpURLConnection) url.openConnection();
			conn.setDoOutput(true);
			conn.setRequestMethod("PUT");
			conn.setRequestProperty("Content-Type", "application/json");  
			
		} catch (MalformedURLException e) {     
    		e.printStackTrace();     
  	    } catch (IOException e) {     
  	    	e.printStackTrace();     
  	    }
		return conn;
	}
	
	public static ArrayList<Object> get(String uri) {   
		ArrayList<Object> elements = new ArrayList<Object>();
    	try {    		 
    		URL url = new URL("http://"+host+":8080/api/"+uri);
    		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    		conn.setRequestMethod("GET");
    		conn.setRequestProperty("Accept", "application/json");     
    		if (conn.getResponseCode() != 200) {
    			throw new RuntimeException("Failed : HTTP error code : "
    					+ conn.getResponseCode());
    		}     
    		BufferedReader br = new BufferedReader(new InputStreamReader(
    			(conn.getInputStream())));     
    		String output;
    		while ((output = br.readLine()) != null) {
    			System.out.println(output);
    			if (JsonParseTest(output, uri.charAt(0)) != null) {
    				elements.addAll(JsonParseTest(output, uri.charAt(0)));
    			}
    		}     
    		conn.disconnect();     
    	  } catch (MalformedURLException e) {     
    		e.printStackTrace();     
    	  } catch (IOException e) {     
    		e.printStackTrace();     
    	  }  catch (NullPointerException e) {
    		  System.out.println("A tömb üres volt, amivel visszatértünk: "+e);
    	  }
    	return elements;
    }

	private static ArrayList<Object> JsonParseTest(String jsonFile, char type) {
		System.out.println("A json fájl tartalma: "+jsonFile);
		ArrayList<Object> templist = new ArrayList<Object>();
			//If get the whole users, not just one
			if (jsonFile.equals("null")){
				System.out.println("A kiválasztott elem(ek) nem létezik");
			} else if (jsonFile.charAt(0)=='[') {
				Object obj=JSONValue.parse(jsonFile);
				JSONArray arrJSON=(JSONArray)obj;
				for(int i=0;i<arrJSON.size();i++){
					if (type=='u') {
						templist.add(parseUser((JSONObject) arrJSON.get(i)));
					} else if (type=='e') { 
						templist.add(parseEvent((JSONObject) arrJSON.get(i)));
					} else if (type=='p') { 
						templist.add(parsePlace((JSONObject) arrJSON.get(i)));
					} else if (type=='c') { 
						templist.add(parseCalendar((JSONObject) arrJSON.get(i)));
					}
				}
			} else if (jsonFile != null) {
				// read the json file
		        JSONParser jsonParser = new JSONParser();
				JSONObject jsonObject;
				if (type=='u') {			        
					try {
						jsonObject = (JSONObject) jsonParser.parse(jsonFile);
						templist.add(parseUser(jsonObject));
					} catch (ParseException e) {
						System.out.println(e);
						e.printStackTrace();
					}
				} else if (type=='e') { 
					try {
						jsonObject = (JSONObject) jsonParser.parse(jsonFile);
						templist.add(parseEvent(jsonObject));
					} catch (ParseException e) {
						System.out.println(e);
						e.printStackTrace();
					}
				} else if (type=='p') { 
					try {
						jsonObject = (JSONObject) jsonParser.parse(jsonFile);
						templist.add(parsePlace(jsonObject));
					} catch (ParseException e) {
						System.out.println(e);
						e.printStackTrace();
					}
				} else if (type=='c') { 
					try {
						jsonObject = (JSONObject) jsonParser.parse(jsonFile);
						templist.add(parseCalendar(jsonObject));
					} catch (ParseException e) {
						System.out.println(e);
						e.printStackTrace();
					}
				}
			} 
			return templist;
	}
	
	public static calendars parseCalendar(JSONObject jsonObject) {
		calendars calendar = new calendars();
		try {	
	        // get datas from the JSON object
	        String userId = (String) jsonObject.get("uid");
	        calendar.setUserId(userId);
	        System.out.println("The id is: " + userId);
	        String name = (String) jsonObject.get("name");
	        calendar.setName(name);
	        System.out.println("The name is: " + name);
	        String from= (String) jsonObject.get("from");
	        calendar.setFrom(from);
	    	System.out.println("The start date is: " + from);
	    	String to= (String) jsonObject.get("to");
	    	calendar.setTo(to);
	        // handle a structure into the json object
	        JSONObject loc = (JSONObject) jsonObject.get("loc");
	        if (loc != null) {
		        if (loc.get("coordinates") != null) {
		        	//hibalehetőség , ha egész számokat kap a json-ból!
		        	JSONArray locarr = (JSONArray)loc.get("coordinates");
		        	System.out.println("lat: "+locarr.get(0));
		        	System.out.println("lon: "+locarr.get(1));
		        	calendar.setLat( (Double) locarr.get(0));
		        	calendar.setLon( (Double) locarr.get(1));	        	
		        } else {
		        	calendar.setLat((Double) loc.get("lat"));
		        	System.out.println("the lat is: "+ loc.get("lat"));
		        	calendar.setLon((Double) loc.get("lon"));
		        	System.out.println("the lon is: "+ loc.get("lon"));
		        }
	        }
		} catch (NullPointerException ex) {
            ex.printStackTrace();
        }
		return calendar;
	}
	
	public static users parseUser(JSONObject jsonObject){
		users user = new users();
		try {
	        // get datas from the JSON object
	        String id = (String) jsonObject.get("_id");
	        user.setId(id);
	        System.out.println("The id is: " + id);
	        String pass = (String) jsonObject.get("pass");
	        System.out.println("The password name is: " + pass);
	        user.setPass(pass);
	        String email = (String) jsonObject.get("email");
	        System.out.println("The email is: " + email);
	        user.setEmail(email);
	            // get an array from the JSON object
	        JSONArray events= (JSONArray) jsonObject.get("public_events");             
	        // take the elements of the json array
	        List<String> publicEvents = new ArrayList<String>();
	        for(int i=0; i<events.size(); i++){
	            System.out.println("The " + i + ". st/nd/th event id is: "+events.get(i));
	            publicEvents.add((String) events.get(i));
	        }
	        user.setPublicEvents(publicEvents);
		} catch (NullPointerException ex) {
            ex.printStackTrace();
        }
		return user;
	
	}
	
	public static places parsePlace(JSONObject jsonObject) {
		places place = new places();
		try {	
	        // get datas from the JSON object
	        String id = (String) jsonObject.get("_id");
	        place.setId(id);
	        System.out.println("The id is: " + id);
	        int zip = ((Long) jsonObject.get("zip")).intValue();
	        place.setZip(zip);
	        // handle a structure into the json object
	        JSONObject loc = (JSONObject) jsonObject.get("loc");
	        // itt mondjuk eldönthetjük hogy dobjon egy errort, ha nincs koordináta az eseményhez
	        if (loc != null) {
		        if (loc.get("coordinates") != null) {
		        	//hibalehetőség , ha egész számokat kap a json-ból!!!
		        	JSONArray locarr = (JSONArray)loc.get("coordinates");
		        	System.out.println("lat: "+locarr.get(0));
		        	System.out.println("lon: "+locarr.get(1));
		        	place.setLat( (Double) locarr.get(0));
		        	place.setLon( (Double) locarr.get(1));	        	
		        } else {
		        	place.setLat((Double) loc.get("lat"));
		        	System.out.println("the lat is: "+ loc.get("lat"));
		        	place.setLon((Double) loc.get("lon"));
		        	System.out.println("the lon is: "+ loc.get("lon"));
		        }
	        }
		} catch (NullPointerException ex) {
            ex.printStackTrace();
        }
		return place;
	}
	
	public static events parseEvent(JSONObject jsonObject) {
		events event = new events();
		try {
	        // get datas from the JSON object
	        String id = (String) jsonObject.get("_id");
	        event.setId(id);
	        System.out.println("The id is: " + id);
	        String name = (String) jsonObject.get("name");
	        event.setName(name);
	        System.out.println("The name is: " + name);
	    	String from= (String) jsonObject.get("from");
	    	event.setFrom(from);
	    	System.out.println("The start date is: " + from);
	    	String to= (String) jsonObject.get("to");
	    	event.setTo(to);
	    	String place= (String) jsonObject.get("place");
	    	event.setPlace(place);
		} catch (NullPointerException ex) {
            ex.printStackTrace();
        }
		return event;
	}
	
}